You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

133 lines
3.3 KiB

"use client";
import { useEffect, useMemo, useState } from "react";
import {
getQuestionAnswersStorageKey,
hasQuestionAnswerValue,
} from "@/components/questions/question-answer-storage";
import InformationSheet from "@/components/ui/information-sheet";
import type { MarriageField, MarriagePhoneFieldValue } from "@/hooks/marriage/types";
import { useMarriageSectionsQuery } from "@/hooks/marriage/use-sections";
type AnswerPaceSheetProps = {
continueLabel: string;
description: string;
slug: string;
title: string;
};
type StoredQuestionAnswers = {
fields?: unknown;
};
function isMarriageField(value: unknown): value is MarriageField {
if (!value || typeof value !== "object") {
return false;
}
const field = value as Partial<MarriageField>;
return (
typeof field.key === "string" &&
typeof field.label === "string" &&
typeof field.type === "string" &&
(field.value === null ||
typeof field.value === "string" ||
typeof field.value === "number" ||
typeof field.value === "boolean" ||
isMarriagePhoneFieldValue(field.value))
);
}
function isMarriagePhoneFieldValue(
value: unknown,
): value is MarriagePhoneFieldValue {
if (!value || typeof value !== "object") {
return false;
}
const phoneValue = value as Partial<MarriagePhoneFieldValue>;
return (
typeof phoneValue.countryCode === "string" &&
typeof phoneValue.phoneNumber === "string"
);
}
function hasStoredQuestionProgress(slugs: readonly string[]) {
try {
return slugs.some((slug) => {
const rawValue = window.localStorage.getItem(
getQuestionAnswersStorageKey(slug),
);
if (!rawValue) {
return false;
}
const storedValue = JSON.parse(rawValue) as StoredQuestionAnswers;
const fields = Array.isArray(storedValue.fields)
? storedValue.fields.filter(isMarriageField)
: [];
return fields.some((field) => hasQuestionAnswerValue(field.value));
});
} catch {
return false;
}
}
export default function AnswerPaceSheet({
continueLabel,
description,
slug,
title,
}: AnswerPaceSheetProps) {
const { data: sections, isSuccess } = useMarriageSectionsQuery();
const [hasSeenSheet, setHasSeenSheet] = useState(true);
const [hasLocalProgress, setHasLocalProgress] = useState(true);
const storageKey = `marriage:sections:${slug}:answer-pace-sheet-seen`;
const sectionSlugs = useMemo(
() => sections?.map((section) => section.slug) ?? [slug],
[sections, slug],
);
const hasAnySectionProgress = useMemo(() => {
if (!sections?.length) {
return true;
}
return sections.some(
(section) => section.current_step > 0 || section.completion_percent >= 1,
);
}, [sections]);
const isOpen =
isSuccess && !hasSeenSheet && !hasLocalProgress && !hasAnySectionProgress;
useEffect(() => {
setHasSeenSheet(window.sessionStorage.getItem(storageKey) === "true");
setHasLocalProgress(hasStoredQuestionProgress(sectionSlugs));
}, [sectionSlugs, storageKey]);
useEffect(() => {
if (!isOpen) {
return;
}
window.sessionStorage.setItem(storageKey, "true");
}, [isOpen, storageKey]);
if (!isOpen) {
return null;
}
return (
<InformationSheet
icon="play"
title={title}
description={description}
buttons={continueLabel}
/>
);
}